#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xmlregexp.h> 
#include <libxml/xmlreader.h>
 
#include "xmlParser.h"
#include "matchers.h"
#include "regex.h"
 

Matchers *APPLI1_Matchers;
int matcher_num;
char *raw_log_path; 	
char *norm_log_root_path;
char *norm_log_file_path;	
char *pipe_log_path;

/////////////////////////////////////////////////////////////////
char* trim (char *s)
{
    int i;

    while (isspace (*s)) s++;    
    for (i = strlen (s) - 1; (isspace (s[i])); i--) ; 
    s[i + 1] = '\0';
    return s;
}
 
xmlXPathObjectPtr getnodeset (xmlDocPtr file, xmlChar *xpath)
{
	xmlXPathContextPtr context;
	xmlXPathObjectPtr result;
	context = xmlXPathNewContext(file);
	 
	result = xmlXPathEvalExpression(xpath, context);
	xmlXPathFreeContext(context);
	return result;
}

void Parse_File(xmlTextReaderPtr reader,const char  *ConfigFile) 
{
	const xmlChar *name ;	
	name = xmlTextReaderConstName(reader);

	Tags *tag;
	Indexs *indexs;
	Fields *fields;
 
	pcre *pcre_pattern;
	tag = Tags_init(); 
	indexs = Indexs_init(); 
	fields = Fields_init(); 

 	char *precheck = malloc (sizeof (*precheck) * 1024);
	char *value_path = malloc (sizeof (*value_path) * 1024);
	char *value_path2 = malloc (sizeof (*value_path2) * 1024);
	char *pattern = malloc (sizeof (*pattern) * 1024);
	
	int matcher_id;

	sprintf(value_path,"/log/matchers/matcher[%d]",matcher_num);
	sprintf(value_path2,"/log/matchers/matcher[%d]",matcher_num);

	xmlDocPtr XML_Conf; 

	xmlNodeSetPtr id_nodeset;
	xmlXPathObjectPtr id_node;

	xmlNodeSetPtr precheck_nodeset;
	xmlXPathObjectPtr precheck_node;

	xmlNodeSetPtr pattern_nodeset;
	xmlXPathObjectPtr pattern_node;

	xmlNodeSetPtr tag_nodeset;
	xmlXPathObjectPtr tag_node;

	xmlNodeSetPtr index_name_nodeset;
	xmlXPathObjectPtr index_name_node;

	xmlNodeSetPtr index_prio_nodeset;
	xmlXPathObjectPtr index_prio_node;
	
	xmlNodeSetPtr field_name_nodeset;
	xmlXPathObjectPtr field_name_node;

	int i;

	XML_Conf = xmlParseFile(ConfigFile);
 
 	if((xmlTextReaderDepth(reader) == 2 && xmlTextReaderNodeType(reader) == 1)
	&&
	!xmlStrcmp(name, (const xmlChar *) "matcher")) 
	{
		printf(" nous sommes dans matcher %d \n", matcher_num);
		////////////////////////////
		strcat(value_path,"/@id");

		id_node = getnodeset (XML_Conf, ( xmlChar *) value_path );
		if (id_node) 
		{
			id_nodeset = id_node->nodesetval;
		 	matcher_id = atoi((char*)xmlNodeListGetString(XML_Conf, id_nodeset->nodeTab[0]->xmlChildrenNode, 1));				 
			//printf("ID:---%d\n",matcher_id  );
 
		strcpy(value_path,"");
		sprintf(value_path,"/log/matchers/matcher[%d]",matcher_num);
		}
		////////////////////////////
		strcat(value_path,"/precheck");

		precheck_node = getnodeset (XML_Conf, ( xmlChar *) value_path );
		if (precheck_node) 
		{
			precheck_nodeset = precheck_node->nodesetval;
 			strcpy(precheck, (const char*)xmlNodeListGetString(XML_Conf, precheck_nodeset->nodeTab[0]->xmlChildrenNode, 1) );				
			//printf("precheck:---%s\n",precheck );
 
		strcpy(value_path,"");
		sprintf(value_path,"/log/matchers/matcher[%d]",matcher_num);
		}
		////////////
		strcat(value_path,"/pattern");

		pattern_node = getnodeset (XML_Conf, ( xmlChar *) value_path );
		if (pattern_node) 
		{
			pattern_nodeset = pattern_node->nodesetval;
			strcpy(pattern, (const char*) xmlNodeListGetString(XML_Conf, pattern_nodeset->nodeTab[0]->xmlChildrenNode, 1));
			trim(pattern);
			//printf("pattern:---%s\n", pattern );
		 	pcre_pattern = compile_regex(pattern);
 
		strcpy(value_path,"");
		sprintf(value_path,"/log/matchers/matcher[%d]",matcher_num);
		}
 		////////////
		strcat(value_path,"/tags/tag");

		tag_node = getnodeset (XML_Conf, ( xmlChar *) value_path );
		if (tag_node) 
		{
			tag_nodeset = tag_node->nodesetval;
			for (i=0; i < tag_nodeset->nodeNr; i++) 
			{
				//printf("tag:---%s\n", xmlNodeListGetString(XML_Conf, tag_nodeset->nodeTab[i]->xmlChildrenNode, 1) );
				Add_Tag(tag,(char *) xmlNodeListGetString(XML_Conf, tag_nodeset->nodeTab[i]->xmlChildrenNode, 1));				
		 	}
		strcpy(value_path,"");
		sprintf(value_path,"/log/matchers/matcher[%d]",matcher_num);
		}
		///////////////
		strcat(value_path,"/fields/index/name");
		strcat(value_path2,"/fields/index/priority");
 
		index_name_node = getnodeset (XML_Conf, ( xmlChar *) value_path);
		index_prio_node = getnodeset (XML_Conf, ( xmlChar *) value_path2);
		if (index_name_node) 
		{
			index_name_nodeset = index_name_node->nodesetval;
			index_prio_nodeset = index_prio_node->nodesetval;

			for (i=0; i < index_name_nodeset->nodeNr; i++) 
			{
				//printf("name:---%s\n", xmlNodeListGetString(XML_Conf, name_nodeset->nodeTab[i]->xmlChildrenNode, 1) );
				//printf("prio:---%s\n", xmlNodeListGetString(XML_Conf, index_prio_nodeset->nodeTab[i]->xmlChildrenNode, 1));

				Add_Indexs(indexs, (char *) xmlNodeListGetString(XML_Conf, index_name_nodeset->nodeTab[i]->xmlChildrenNode, 1), atoi((const char *)xmlNodeListGetString(XML_Conf, index_prio_nodeset->nodeTab[i]->xmlChildrenNode, 1)));		 	
		 	}
		strcpy(value_path,"");
		strcpy(value_path2,"");
		sprintf(value_path,"/log/matchers/matcher[%d]",matcher_num);
		sprintf(value_path2,"/log/matchers/matcher[%d]",matcher_num);
		}
		//////////////
		strcat(value_path,"/fields/field/name");
 
		field_name_node = getnodeset (XML_Conf, ( xmlChar *) value_path);
		if (field_name_node) 
		{
			field_name_nodeset = field_name_node->nodesetval;

			for (i=0; i < field_name_nodeset->nodeNr; i++) 
			{
				//printf("field name:---%s\n", xmlNodeListGetString(XML_Conf, name_nodeset->nodeTab[i]->xmlChildrenNode, 1));
				Add_Fields(fields,(char *) xmlNodeListGetString(XML_Conf, field_name_nodeset->nodeTab[i]->xmlChildrenNode, 1));
		 	}
		strcpy(value_path,"");
		sprintf(value_path2,"/log/matchers/matcher[%d]",matcher_num);
		}
		/////////////

	 Add_Matcher(APPLI1_Matchers, matcher_id, precheck, pcre_pattern, tag, indexs, fields);
	 //Print_Matchers(APPLI1_Matchers);
	}


	if((xmlTextReaderDepth(reader) == 2 && xmlTextReaderNodeType(reader) == 15)
	&&
	!xmlStrcmp(name, (const xmlChar *) "matcher")) 
	{
		printf(" nous sommes à la fin du matcher %d \n", matcher_num); 
 
		Tags_free(tag);
		Indexs_free(indexs);
		Fields_free(fields);
		printf("--------------------------------------------------\n"); 

		free(pattern);
		free(value_path2);
		free(value_path); 
		free(precheck);
		
		matcher_num++;
	}
	
 	xmlFreeDoc(XML_Conf);
	xmlCleanupParser();
}

void Fill_Matchers(const char *filename) 
{
	xmlTextReaderPtr reader;
    	int ret;

	xmlDocPtr XML_Conf;
 
		
 	xmlNodeSetPtr raw_log_path_nodeset;
	xmlXPathObjectPtr raw_log_path_node;
	
	xmlNodeSetPtr norm_log_root_path_nodeset;
	xmlXPathObjectPtr norm_log_root_path_node;

	xmlNodeSetPtr norm_log_file_path_nodeset;
	xmlXPathObjectPtr norm_log_file_path_node;
	
	xmlNodeSetPtr pipe_log_path_nodeset;
	xmlXPathObjectPtr pipe_log_path_node;	
	
	raw_log_path = malloc (sizeof (*raw_log_path) * 1024);
	norm_log_root_path = malloc (sizeof (*norm_log_root_path) * 1024);
	pipe_log_path = malloc (sizeof (*pipe_log_path) * 1024);
	norm_log_file_path = malloc (sizeof (*norm_log_file_path) * 1024);
	
	XML_Conf = xmlParseFile(filename);
	
	///////////////
	raw_log_path_node = getnodeset (XML_Conf, ( xmlChar *) "/log/raw_log_path" );
	if (raw_log_path_node) 
	{
		raw_log_path_nodeset = raw_log_path_node->nodesetval;
		strcpy(raw_log_path, (const char*)xmlNodeListGetString(XML_Conf, raw_log_path_nodeset->nodeTab[0]->xmlChildrenNode, 1) );				
		printf("logpath:---%s\n",raw_log_path );
 
	} 
///////////
	norm_log_root_path_node = getnodeset (XML_Conf, ( xmlChar *) "/log/norm_log_root_path" );
	if (norm_log_root_path_node) 
	{
		norm_log_root_path_nodeset = norm_log_root_path_node->nodesetval;
		strcpy(norm_log_root_path, (const char*)xmlNodeListGetString(XML_Conf, norm_log_root_path_nodeset->nodeTab[0]->xmlChildrenNode, 1) );				
		printf("logpath:---%s\n",norm_log_root_path );
 
	} 
////////////
	norm_log_file_path_node = getnodeset (XML_Conf, ( xmlChar *) "/log/norm_log_file_path" );
	if (norm_log_file_path_node) 
	{
		norm_log_file_path_nodeset = norm_log_file_path_node->nodesetval;
		strcpy(norm_log_file_path, (const char*)xmlNodeListGetString(XML_Conf, norm_log_file_path_nodeset->nodeTab[0]->xmlChildrenNode, 1) );				
		printf("logpath:---%s\n",norm_log_file_path );
 
	} 
///////
	pipe_log_path_node = getnodeset (XML_Conf, ( xmlChar *) "/log/pipe_log_path" );
	if (pipe_log_path_node) 
	{
		pipe_log_path_nodeset = pipe_log_path_node->nodesetval;
		strcpy(pipe_log_path, (const char*)xmlNodeListGetString(XML_Conf, pipe_log_path_nodeset->nodeTab[0]->xmlChildrenNode, 1) );				
		printf("logpath:---%s\n",pipe_log_path );
 
	} 
	 ///////////////// 
	 
	matcher_num = 1;

    	reader = xmlReaderForFile(filename, NULL, 0);
    	
	if (reader != NULL) 
	{
        	ret = xmlTextReaderRead(reader);
        	while (ret == 1) 
		{
            		Parse_File(reader, filename);
            		ret = xmlTextReaderRead(reader);
        	}
        	xmlFreeTextReader(reader);
        	
    	} 
	
}
